package com.lanyou.esb.service;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.wsdl.WSDLException;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.eviware.soapui.impl.wsdl.WsdlInterface;
import com.eviware.soapui.impl.wsdl.WsdlOperation;
import com.eviware.soapui.impl.wsdl.WsdlProject;
import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlImporter;
import com.eviware.soapui.model.iface.Operation;
import com.google.gson.JsonObject;
import com.lanyou.esb.common.CommonUtils;
import com.lanyou.esb.datadictionary.ContentType;
import com.lanyou.esb.repository.WsdlMetaDataDetailRepository;
import com.lanyou.esb.repository.WsdlMetaDataRepository;
import com.lanyou.esb.vo.WsMethodInfo;
import com.lanyou.esb.wsdl.domain.OperationInfo;
import com.lanyou.esb.wsdl.domain.ServiceInfo;
import com.lanyou.esb.wsdl.util.ComponentBuilder;
import com.primeton.esb.sam.wsdl.WSDLToSoap;


@Service
public class WsdlMetaDataService {
	
	@Autowired
	private WsdlMetaDataRepository wsdlMetaDataRepository;  
	
	@Autowired
	private WsdlMetaDataDetailRepository wsdlMetaDataDetailRepository;  

	
	/**
	 * 解析wsdl地址
	 * @param wsdlUrl	wsdl地址
	 * @return
	 */
	public  String parseWsdl(String wsdlUrl){
		
		String operations = "";
		try {
			operations = WSDLToSoap.getWsdlOperation(wsdlUrl);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		String operationData = "";
		
		if(StringUtils.isNotBlank(operations)){
			if(operations.indexOf(",") != -1){
				String[]  operS = operations.split(",");
				JsonObject jsonObject = new JsonObject();
				for (String operation : operS) {
					if(jsonObject.has(operation)){
						
					}else{
					   jsonObject.addProperty(operation, operation);
					   operationData += operation + ",";
					}
				}
				
				operationData = operationData.substring(0, operationData.length()-1);
			}else{
				operationData = operations;
			}
			
		}
		
		return operationData;
	}
	
	/**
	 * 获取接口请求报文
	 * @param wsdlUrl	wsdl地址
	 * @param operation	接口方法
	 * @return
	 */
	/*public static String getSoapRequestMsg(String wsdlUrl, String  operation){
    	return WSDLToSoap.getSoapMessage(wsdlUrl, operation);
	}*/
	
	
	
    public String getSoapReponsetMsg(String wsdlURL, String operation, String requestBody, String soapProtocol) {
    	
    	HttpClient client = HttpClients.createDefault();
		HttpPost post = new HttpPost(wsdlURL);
		String soapReponseMsg = "";
		try {
			HttpEntity re = new StringEntity(requestBody,"UTF-8");
			if(soapProtocol.equals(ContentType.SOAP11.ValueCode)){
				post.setHeader("Content-Type",CommonUtils.CONTENTYPE_TEXT_XML);
			}else{
				post.setHeader("Content-Type",CommonUtils.CONTENTYPE_APP_SOAP_XML);
			}
			
			/*post.setHeader("Content-Length", String.valueOf(requestBody.length()));*/
			
			String soapActionUri = getSoapActionByOperation(wsdlURL, operation);
			post.setHeader("SOAPAction", soapActionUri);
			post.setEntity(re);		
			HttpResponse response = client.execute(post);
			System.out.println("请求服务的Soap文本："+EntityUtils.toString(post.getEntity()));
			System.out.println("请求服务结果状态:"+response.getStatusLine());
			//System.out.println("请求服务返回XML文本："+EntityUtils.toString(response.getEntity()));
			soapReponseMsg = EntityUtils.toString(response.getEntity());
			
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (WSDLException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		JsonObject jsonObject = new JsonObject();
    	jsonObject.addProperty("soapReponseMsg", soapReponseMsg);
    	return jsonObject.toString();
		
    }
    
    /**
     * 根据wsdl地址获取接口列表
     * @param wsdlAddress webservice的wsdl地址
     * @return
     * @throws WSDLException
     * @throws Exception
     */
    /*public String getInterfaceCodes(String wsdlAddress) throws WSDLException, Exception{
    	String interfaceCodes = "";
    	ComponentBuilder builder = new ComponentBuilder();
		ServiceInfo serviceInfo = new ServiceInfo();
		serviceInfo.setWsdllocation(wsdlAddress);
		serviceInfo = builder.buildserviceinformation(serviceInfo);
		Iterator iter = serviceInfo.getOperations();
		while (iter.hasNext()) {
			OperationInfo oper = (OperationInfo) iter.next();
			interfaceCodes += (interfaceCodes.isEmpty()?"":",") + oper.getTargetMethodName();
		}
		
		return interfaceCodes;
    }*/
    
    
    
    /*public String getSoapActionByOperation(String wsdlAddress, String operationName) throws WSDLException, Exception{
    	String soapActionUri = "";
    	ComponentBuilder builder = new ComponentBuilder();
		ServiceInfo serviceInfo = new ServiceInfo();
		serviceInfo.setWsdllocation(wsdlAddress);
		serviceInfo = builder.buildserviceinformation(serviceInfo);
		Iterator iter = serviceInfo.getOperations();
		while (iter.hasNext()) {
			OperationInfo oper = (OperationInfo) iter.next();
			if(StringUtils.equals(operationName, oper.getTargetMethodName())){
				soapActionUri = oper.getSoapActionURI();
				break;
			}
		}
		
		return soapActionUri;
    }*/
    
    
    //新的获取接口编码的方法（支持cxf、axis2、spring-ws和c#）
    public String getInterfaceCodes(String wsdlAddress) throws Exception{
    	String interfaceCodes = "";
    	List<WsMethodInfo> wsMethodInfoList = getProBySoap(wsdlAddress);
    	for (WsMethodInfo wsMethodInfo : wsMethodInfoList) {
    		interfaceCodes += (interfaceCodes.isEmpty()?"":",") + wsMethodInfo.getMethodName();
		}
    	
    	return interfaceCodes;
    }
    
    
    //新的获取接口请求报文（支持cxf、axis2、spring-ws和c#）
    public static String getSoapRequestMsg(String wsdlUrl, String  operation) throws Exception{
    	String soapRequestMsg = "";
    	List<WsMethodInfo> wsMethodInfoList = getProBySoap(wsdlUrl);
    	for (WsMethodInfo wsMethodInfo : wsMethodInfoList) {
    		if(StringUtils.equals(wsMethodInfo.getMethodName(), operation)){
    			soapRequestMsg = wsMethodInfo.getMethodSoapAction();
    		}
		}
    	return soapRequestMsg;
	}
    
    
    public String getSoapActionByOperation(String wsdlAddress, String operationName) throws WSDLException, Exception{
    	String soapActionUri = "";
    	List<WsMethodInfo> wsMethodInfoList = getProBySoap(wsdlAddress);
    	for (WsMethodInfo wsMethodInfo : wsMethodInfoList) {
    		if(StringUtils.equals(wsMethodInfo.getMethodName(), operationName)){
    			soapActionUri = wsMethodInfo.getSoapActionUri();
    		}
		}
    	return soapActionUri;
    }
    

	public static List<WsMethodInfo> getProBySoap(String address) throws Exception {
		URL url = new URL(address);
		InputStream openStream = url.openStream();
		openStream.close();

		Map<String, Object> result = new HashMap<String, Object>();
		Map<String, String> soapActionUriMap = new HashMap<String, String>();
		WsdlProject project = new WsdlProject();
		WsdlInterface[] wsdls = WsdlImporter.importWsdl(project, address);

		WsdlInterface wsdl = wsdls[0];
		List<Operation> operationList = wsdl.getOperationList();
		for (int i = 0; i < operationList.size(); i++) {
			Operation operation = operationList.get(i);
			WsdlOperation op = (WsdlOperation) operation;
			Map<String, Object> tmp = new HashMap<String, Object>();
			tmp.put(op.getName(), op.createRequest(true));
			result.put(i + "", tmp);
			soapActionUriMap.put(op.getName(), op.getAction());
			
		}

		if ((result != null) && (result.size() != 0)) {
			List importWsdl = new ArrayList();
			Set keySet = result.keySet();
			Iterator iterator = keySet.iterator();
			while (iterator.hasNext()) {
				WsMethodInfo info = new WsMethodInfo();
				List inputType = new ArrayList();
				List inputNames = new ArrayList();
				List isparent = new ArrayList();
				String next = "" + iterator.next();
				HashMap hashMap = (HashMap) result.get(next);
				Set keySet2 = hashMap.keySet();
				Iterator iterator2 = keySet2.iterator();
				if (iterator2.hasNext()) {
					String next2 = (String) iterator2.next();
					String string = (String) hashMap.get(next2);
					// 处理targetNameSpace
					String qname = string.substring(
							string.lastIndexOf("\"http://") + 1,
							string.lastIndexOf("\">"));
					info.setTargetNameSpace(qname);

					String soap11 = "http://schemas.xmlsoap.org/soap/envelope";
					String soap12 = "http://www.w3.org/2003/05/soap-envelope";
					InputStreamReader is = new InputStreamReader(
							new ByteArrayInputStream(string.getBytes("utf-8")));
					BufferedReader ibr = new BufferedReader(is);
					String readLine = ibr.readLine();
					if (readLine != null) {
						if (readLine.indexOf(soap11) >= 0)
							info.setTargetXsd("11");
						else if (readLine.indexOf(soap12) >= 0) {
							info.setTargetXsd("12");
						}
					}
					ibr.close();
					is.close();

					info.setMethodSoapAction(string);

					Document read = DocumentHelper.parseText(string);
					Element rootElement = read.getRootElement();
					List<Element> elements = rootElement.elements();
					for (Element element : elements) {
						if ("Body".equals(element.getName())) {
							List<Element> elements2 = element.elements();
							info.setMethodName(next2);
							info.setSoapActionUri(soapActionUriMap.get(next2));
							for (Element element2 : elements2) {
								getParameter(element2, 1, 1, inputType,
										inputNames, isparent);
								info.setInputNames(inputNames);
								info.setInputType(inputType);
								info.setOutputType(isparent);
							}
						}
					}

					importWsdl.add(info);
				}
			}
			return importWsdl;
		}
		return null;
	}
	
	
	
	public static void getParameter(Element element2, int gen, int genParent,
			List<String> inputType, List<String> inputNames,
			List<String> isparent) {
		if (element2 != null) {
			List<Element> elements3 = element2.elements();
			if ((elements3 != null) && (elements3.size() != 0))
				for (Element element : elements3) {
					inputType.add(gen + "," + genParent);
					inputNames.add(element.getQualifiedName());
					if (element != null) {
						List e = element.elements();
						if ((e != null) && (e.size() != 0)) {
							isparent.add("1");
							int gen1 = gen + gen;
							getParameter(element, gen1, gen, inputType,
									inputNames, isparent);
						} else {
							isparent.add("0");
						}
					}
				}
		}
	}
    
}
